package work.sajor.wechatpush.util;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonArray;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.binary.StringUtils;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.RandomAccessFile;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * appid：663699e80a524e82b2bf083116fb90cb
 * secret：0tP3qe76wQRVm2LS
 * rsa：MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALlPx8r+WlHz3ZUXCIHiuY88xZIeMAlHSFSXzUUFla6EJU2pAL7R/Gwvb2bRYXC2Ay4qOFi2B+5hmCyJLYQqNfv4/NtZT5DAVhjvKJLS4Jzn1vYt78+UnCzr2D26BG1ZsP1i6S6/SEaNmcw7QleUU54ptkpFbHf/dSYnezLSUx61AgMBAAECgYEAtSnfwv4iwpfMemLIOGK00emxpQXKJGgBuGGnleC90pzx8xhT2Dlls0Y0fKoZvpzSQyGXcHKVEmFq6a86RkkV+BQbS80+DlE5rDDSoqZTTqkVwwWpTPQ6FnGa/KYyWyUWylZfat3L5JCOX6z2Zuhp5UcpEsosxgs29nAXpXZU+wkCQQDeuOCwUEKbUfGh+rxwOsTxDo/mkqZCoRun9DDNJmI99wjCeYMN/ZxtPVtA+al/FJlWYlGw7YWOSia79tcoyENPAkEA1P/zLZzg8FyilKZKs8iDhM9NtTwE6fhnVxyxB28s36PvF5Qxmu/j8P4/Vq/Adapd3i3By4R31xerE3YD+WnMuwJBANQv5Hh1bo+VKRS90WtGwjw6OGReEKHn5XZEkX3RdMU+Jg1JQM9CcBYu31JuyMl2cYO4FcXu9E+UW4S17VRAPscCQHsOsIjutMpJSqjE9i2uL8XAGu4VEeW23MVoTyKzaWJ/jLe7p3kTFUb7LM7BVVjlp7ugBfG1w6LiCrWAnkUvidcCQGkgHbXuf7TKvTbloQAGaY2oLF8mZ/LyIgJapDHNwvGNRa/8IzZu4zL68zgLh5AfcJeftXpUaGharPmFtIHTwZE=
 */
@Slf4j
public class ChinaMobileApiTest {

    private static final String APP_ID = "663699e80a524e82b2bf083116fb90cb";
    private static final String SECRET = "0tP3qe76wQRVm2LS";
    private static final String RSA = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALlPx8r+WlHz3ZUXCIHiuY88xZIeMAlHSFSXzUUFla6EJU2pAL7R/Gwvb2bRYXC2Ay4qOFi2B+5hmCyJLYQqNfv4/NtZT5DAVhjvKJLS4Jzn1vYt78+UnCzr2D26BG1ZsP1i6S6/SEaNmcw7QleUU54ptkpFbHf/dSYnezLSUx61AgMBAAECgYEAtSnfwv4iwpfMemLIOGK00emxpQXKJGgBuGGnleC90pzx8xhT2Dlls0Y0fKoZvpzSQyGXcHKVEmFq6a86RkkV+BQbS80+DlE5rDDSoqZTTqkVwwWpTPQ6FnGa/KYyWyUWylZfat3L5JCOX6z2Zuhp5UcpEsosxgs29nAXpXZU+wkCQQDeuOCwUEKbUfGh+rxwOsTxDo/mkqZCoRun9DDNJmI99wjCeYMN/ZxtPVtA+al/FJlWYlGw7YWOSia79tcoyENPAkEA1P/zLZzg8FyilKZKs8iDhM9NtTwE6fhnVxyxB28s36PvF5Qxmu/j8P4/Vq/Adapd3i3By4R31xerE3YD+WnMuwJBANQv5Hh1bo+VKRS90WtGwjw6OGReEKHn5XZEkX3RdMU+Jg1JQM9CcBYu31JuyMl2cYO4FcXu9E+UW4S17VRAPscCQHsOsIjutMpJSqjE9i2uL8XAGu4VEeW23MVoTyKzaWJ/jLe7p3kTFUb7LM7BVVjlp7ugBfG1w6LiCrWAnkUvidcCQGkgHbXuf7TKvTbloQAGaY2oLF8mZ/LyIgJapDHNwvGNRa/8IzZu4zL68zgLh5AfcJeftXpUaGharPmFtIHTwZE=";

    private static String token = "eyJhbGciOiJIUzI1NiJ9.eyJwcm9mZXNzaW9uIjoxLCJhcHBpZCI6IjY2MzY5OWU4MGE1MjRlODJiMmJmMDgzMTE2ZmI5MGNiIiwib3BlcmF0b3JUeXBlIjoxLCJvcGVyYXRvciI6IjY2MzY5OWU4MGE1MjRlODJiMmJmMDgzMTE2ZmI5MGNiIiwianRpIjoiMTMwMTU0NDczMTE1MTcxNjM1MyIsImlhdCI6MTY2MTk0MzQyMywic3ViIjoiNjYzNjk5ZTgwYTUyNGU4MmIyYmYwODMxMTZmYjkwY2IiLCJleHAiOjE2NjI1NDgyMjN9.YzX-bhVmIqNK5leqAlVoF0OAlqrcR21YCip1If112Tc";

    public static final String FILE_PREFIX = "|";

    public static void init() {
    }

    private static String getSign() {
        try {

            return Hex.encodeHexString(MessageDigest.getInstance("MD5").digest(StringUtils.getBytesUtf8(APP_ID + SECRET)));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void main(String[] args) throws Exception {
//        getToken();
//        getDeviceList();

//        liveV1();

        getDevicesRtmp();
    }

    private static void getDevicesRtmp() throws Exception {
        int listTotal = getDeviceListTotal(1, 1);
        int pageSize = 100;
        if (listTotal <= 0) {
            return;
        }
        int totalPage = (int) (listTotal / pageSize);
        JSONArray deviceLists = new JSONArray();
        for (int i = 1; i < totalPage + 1; i++) {
            System.err.println("total:" + totalPage);
            JSONArray deviceList = getDeviceList(i, pageSize);
            if (!CollectionUtils.isEmpty(deviceList)) {
                for (int i1 = 0; i1 < deviceList.size(); i1++) {
                    JSONObject jsonObject = deviceList.getJSONObject(i1);
                    String deviceName = jsonObject.getString("deviceName");
                    if (deviceName.contains("江阴澄江澄南路标杆厅") || deviceName.contains("宜兴人民南路标杆厅")) {
                        deviceLists.add(jsonObject);
                    }
                }
            }
        }
        log.info("device_list:{}", deviceLists);
        JSONArray rtmpList = new JSONArray();
        StringBuilder message = new StringBuilder();
        for (int i = 0; i < deviceLists.size(); i++) {
            JSONObject jsonObject = deviceLists.getJSONObject(i);
            String deviceId = jsonObject.getString("deviceId");
            String deviceName = jsonObject.getString("deviceName");
            String deviceRtmp = getDeviceRtmp(deviceId);
            message.append(deviceId);
            message.append(FILE_PREFIX);
            message.append(deviceName);
            message.append(FILE_PREFIX);
            message.append(org.apache.commons.lang3.StringUtils.isEmpty(deviceRtmp) ? "-1" : deviceRtmp);
            message.append("\n");
        }
        log.info("rtmpList:{}", rtmpList);

        writeTxtFile(message.toString(),System.getProperty("user.dir")+ "\\device_rtmp_"+LocalDate.now()+".txt");
    }


    /**
     * 创建文件
     *
     * @param file
     * @return
     */
    public static boolean createFile(File file) throws Exception {
        boolean flag = false;
        try {
            if (file.exists()) {
                file.delete();
            }
            file.createNewFile();
            flag = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

    /**
     * 写文件
     *
     * @param filePath
     * @return
     */
    public static boolean writeTxtFile(String content, String filePath) throws Exception {
        File file = new File(filePath);
        createFile(file);
        RandomAccessFile mm = null;
        boolean flag = false;
        FileOutputStream o = null;
        try {
            o = new FileOutputStream(file);
            o.write(content.getBytes("UTF-8"));
            o.close();
//   mm=new RandomAccessFile(file,"rw");
//   mm.writeBytes(content);
            flag = true;
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        } finally {
            if (mm != null) {
                mm.close();
            }
        }
        return flag;
    }

    private static Map<String, String> buildHttpHeaders(String bodyJson, String token) {
        if (org.apache.commons.lang3.StringUtils.isEmpty(bodyJson)) {
            bodyJson = "{}";
        }
        Map<String, String> headers = new LinkedHashMap<>();
        headers.put("appid", APP_ID);
        headers.put("md5", Md5Util.encrypt32(bodyJson));
        headers.put("timestamp", String.valueOf(System.currentTimeMillis()));
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(token)) {
            headers.put("token", token);
        }
        headers.put("version", "3.1.2");

        try {
        /*
        Base64:java.util
        PKCS8EncodedKeySpec:java.security
        KeyFactory:java.security
        Signature:java.security
         */
            //需要签名字符串
            String jsonString = JSON.toJSONString(headers);
            //RSA密钥
            String privateKey = RSA;
            Base64.Encoder encoder = Base64.getEncoder();
            Base64.Decoder decoder = Base64.getDecoder();
            PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(decoder.decode(privateKey.getBytes()));
            PrivateKey priKey = KeyFactory.getInstance("RSA").generatePrivate(priPKCS8);
            Signature signature = Signature.getInstance("SHA1WithRSA");
            signature.initSign(priKey);
            signature.update(jsonString.getBytes("utf-8"));
            String signarureString = encoder.encodeToString(signature.sign());
            headers.put("signature", signarureString);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return headers;
    }

    private static Map<String, String> buildHttpHeadersV1(String bodyJson, String token) {
        if (org.apache.commons.lang3.StringUtils.isEmpty(bodyJson)) {
            bodyJson = "{}";
        }
        Map<String, String> headers = new LinkedHashMap<>();
        headers.put("appid", APP_ID);
        headers.put("md5", Md5Util.encrypt32(bodyJson));
        headers.put("timestamp", String.valueOf(System.currentTimeMillis()));
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(token)) {
            headers.put("token", token);
        }
        headers.put("version", "1.0.0");

        try {
        /*
        Base64:java.util
        PKCS8EncodedKeySpec:java.security
        KeyFactory:java.security
        Signature:java.security
         */
            //需要签名字符串
            String jsonString = JSON.toJSONString(headers);
            //RSA密钥
            String privateKey = RSA;
            Base64.Encoder encoder = Base64.getEncoder();
            Base64.Decoder decoder = Base64.getDecoder();
            PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(decoder.decode(privateKey.getBytes()));
            PrivateKey priKey = KeyFactory.getInstance("RSA").generatePrivate(priPKCS8);
            Signature signature = Signature.getInstance("SHA1WithRSA");
            signature.initSign(priKey);
            signature.update(jsonString.getBytes("utf-8"));
            String signarureString = encoder.encodeToString(signature.sign());
            headers.put("signature", signarureString);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return headers;
    }


    private static JSONObject transferResult(String result) throws Exception {
        // result
        JSONObject resultJson = JSON.parseObject(result);

        if (null == resultJson || null == resultJson.getString("resultCode")) {

        }
        log.info("transferResult:{}", result);
        String code = resultJson.getString("resultCode");
        String message = resultJson.getString("resultMsg");
        if (!code.equals("000000")) {
            // 失败
            throw new Exception(message);
        }

        return resultJson.getJSONObject("data");
    }

    private static JSONArray transferResultList(String result) throws Exception {
        // result
        JSONObject resultJson = JSON.parseObject(result);

        if (null == resultJson || null == resultJson.getString("resultCode")) {

        }
        log.info("transferResult:{}", result);
        String code = resultJson.getString("resultCode");
        String message = resultJson.getString("resultMsg");
        if (!code.equals("000000")) {
            // 失败
            throw new Exception(message);
        }

        return resultJson.getJSONArray("data");
    }

    private static Integer transferResultTotal(String result) throws Exception {
        // result
        JSONObject resultJson = JSON.parseObject(result);

        if (null == resultJson || null == resultJson.getString("resultCode")) {

        }
        log.info("transferResult:{}", result);
        String code = resultJson.getString("resultCode");
        String message = resultJson.getString("resultMsg");
        if (!code.equals("000000")) {
            // 失败
            throw new Exception(message);
        }

        return resultJson.getIntValue("total");
    }

    /**
     * 申请应用token：
     * {
     *     "operatorType":1,
     *     "sig":"d41d8cd98f00b204e9800998ecf8427e"
     * }
     *
     * 申请设备xxxxS_abcde的只读权限的自定义token：
     * {
     *     "operatorType":2,
     *     "action":"read",
     *     "targetType":2,
     *     "target":"xxxxS_abcde",
     *     "sig":"d41d8cd98f00b204e9800998deca120"
     * }
     */
    /**
     * 请求参数
     * 参数名称	参数类型	是否必需	参数含义	说明
     * operatorType	int	Y	获取token类型	1：应用token(拥有该应用全部权限)，2：自定义token(拥有该应用部分权限)。
     * sig	String	Y	签名(32位小写字符串)	MD5(appId+secret)
     * action	String	N	行为	read：只读，write：可读可写，获取应用token时不传。
     * targetType	String	N	资源类型	2：设备，获取应用token时不传。
     * target	String	N	目标资源	多个设备id以逗号拼接，获取应用token时不传。
     */

    public static void getToken() {
        HashMap<String, Object> params = new HashMap<>();
        params.put("operatorType", 1);
        params.put("sig", getSign());

        try {
            // http
            String url = "https://open.andmu.cn/v3/open/api/token";
            String dataJsonStr = JSON.toJSONString(params);
            String response = HttpConnector.postJsonHeader(buildHttpHeaders(dataJsonStr, null), url, dataJsonStr);
            JSONObject data = transferResult(response);
            if (data != null) {
                token = data.getString("token");
                log.info("token:{}", token);
            }
        } catch (Exception e) {
            log.error("getToken OSDeviceException : ", e);
        }
    }


    public static JSONArray getDeviceList(int page, int pageSize) {
        getToken();
        HashMap<String, Object> params = new HashMap<>();
        params.put("page", page);
        params.put("pageSize", pageSize);

        try {
            // http
            String url = "https://open.andmu.cn/v3/open/api/device/list";
            String dataJsonStr = JSON.toJSONString(params);
            String response = HttpConnector.postJsonHeader(buildHttpHeaders(dataJsonStr, token), url, dataJsonStr);
            JSONArray data = transferResultList(response);
            log.info("device_list:{}", data);
            return data;
        } catch (Exception e) {
            log.error("getDeviceList OSDeviceException : ", e);
        }
        return null;
    }

    public static int getDeviceListTotal(int page, int pageSize) {
        getToken();
        HashMap<String, Object> params = new HashMap<>();
        params.put("page", page);
        params.put("pageSize", pageSize);

        try {
            // http
            String url = "https://open.andmu.cn/v3/open/api/device/list";
            String dataJsonStr = JSON.toJSONString(params);
            String response = HttpConnector.postJsonHeader(buildHttpHeaders(dataJsonStr, token), url, dataJsonStr);
            int data = transferResultTotal(response);
            log.info("getDeviceListTotal:{}", data);
            return data;
        } catch (Exception e) {
            log.error("getDeviceListTotal OSDeviceException : ", e);
        }
        return 0;
    }

    public static String getDeviceRtmp(String deviceInfo) {
        getToken();
        HashMap<String, Object> params = new HashMap<>();
        params.put("deviceId", deviceInfo);
        params.put("endTime", System.currentTimeMillis() + 120 * 1000);

        try {
            // http
            String url = "https://open.andmu.cn/v3/open/api/device/rtmp";
            String dataJsonStr = JSON.toJSONString(params);
            String response = HttpConnector.postJsonHeader(buildHttpHeadersV1(dataJsonStr, token), url, dataJsonStr);
            JSONObject data = transferResult(response);
            log.info("getDeviceRtmp:{}", data);
            return data.getString("rtmpUrl");
        } catch (Exception e) {
            log.error("getDeviceList OSDeviceException : ", e);
        }
        return null;
    }


    public static void liveV1() {
        getToken();
        HashMap<String, Object> params = new HashMap<>();
        params.put("deviceId", "xxxxS_0012313a1e56");
        params.put("endTime", System.currentTimeMillis() + 120 * 1000);

        try {
            // http
            String url = "https://open.andmu.cn/v3/open/api/websdk/player";
            String dataJsonStr = JSON.toJSONString(params);
            String response = HttpConnector.postJsonHeader(buildHttpHeaders(dataJsonStr, token), url, dataJsonStr);
            JSONObject data = transferResult(response);
            if (data != null) {
                String streamUrl = data.getString("url");
                log.info("streamUrl:{}", streamUrl);
            }
        } catch (Exception e) {
            log.error("liveV1 OSDeviceException : ", e);
        }
    }


    public void liveV2() {
        getToken();
        HashMap<String, Object> params = new HashMap<>();
        params.put("deviceId", "xxxxS_30fff693322e");
        params.put("endTime", System.currentTimeMillis() + 120 * 1000);

        try {
            // http
            String url = "https://open.andmu.cn/v3/open/api/websdk/live";
            String dataJsonStr = JSON.toJSONString(params);
            String response = HttpConnector.postJsonHeader(buildHttpHeaders(dataJsonStr, token), url, dataJsonStr);
            JSONObject data = transferResult(response);
            if (data != null) {
                String streamUrl = data.getString("url");
                log.info("streamUrl:{}", streamUrl);
            }
        } catch (Exception e) {
            log.error("liveV2 OSDeviceException : ", e);
        }
    }


    public void playback() {
        HashMap<String, Object> params = new HashMap<>();
        params.put("deviceId", "xx");
        params.put("startTime", System.currentTimeMillis() - 1200 * 1000);
        params.put("endTime", System.currentTimeMillis() - 600 * 1000);

        try {
            // http
            String url = "https://open.andmu.cn/v3/open/api/device/hls/palyback";
            String dataJsonStr = JSON.toJSONString(params);
            String response = HttpConnector.postJsonHeader(buildHttpHeaders(dataJsonStr, token), url, dataJsonStr);
            JSONObject data = transferResult(response);
            if (data != null) {
                String streamUrl = data.getString("url");
                log.info("streamUrl:{}", streamUrl);
            }
        } catch (Exception e) {
            log.error("playback OSDeviceException : ", e);
        }
    }
}
